import Vue from "vue"

class Store {
    constructor(options) {
        // state
        this.vm = new Vue({  // 利用vue的data数据源，让state变成响应式
            data: {
        state: options.state || {}
            }
        })

        // this.state = options.state || {}


        // getters
        let getters = options.getters || {}
        this.getters = {}
        Object.keys(getters).forEach(getterName => {
            Object.defineProperty(this.getters, getterName, { // 数据拦截 {getNum:}
                get: () => {
                    return getters[getterName](this.state)
                }
            })
        })

        // mutations
        let mutations = options.mutations || {}
        this.mutations = {}
        Object.keys(mutations).forEach(mutationName => {
            this.mutations[mutationName] = (arg) => { // 添加
                mutations[mutationName](this.state, arg)
            }
        })

        // actions
        let actions = options.actions
        this.actions = {}
        Object.keys(actions).forEach(actionName => {
            this.actions[actionName] = (arg) => {
                actions[actionName](this, arg) // this是整个vue实例
            }
        })
    }

    dispatch(method, arg) {
        this.actions[method](arg)
    }

    commit = (method, arg) => {  // 注意作用域问题 this
        console.log(this);
        this.mutations[method](arg)
    }


    get state() {  // 函数前面加get，当我们要取函数内部的返回值时，只需要写函数名state就可以
        return this.vm.state
    }

}




let install = function(Vue) {
    Vue.mixin({
        beforeCreate() {
            if (this.$options && this.$options.store) { // $options用来获取根组件
                this.$store = this.$options.store // 往vue身上挂载了
            } else { // 子组件
                this.$store = this.$parent && this.$parent.$store 
            }
        },
    })
}


let Vuex = {
    Store,
    install
}

export default Vuex